package org.zoomdev.zoom.rpc.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.zoomdev.zoom.rpc.HeartbeatService;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RpcUtils {
    public static final short FUNC_ERROR = (short) 0xffff;

    public static List<Method> findPublicMethods(Class<?> type) {
        Method[] methods = type.getMethods();
        List<Method> list = new ArrayList<Method>(methods.length);
        for (Method method : methods) {
            if (Modifier.isStatic(method.getModifiers())) {
                continue;
            }
            Class<?> cls = method.getDeclaringClass();
            if (cls != Object.class) {
                list.add(method);
            }
        }
        return list;
    }


    /**
     * 提供泛型List type的构造
     *
     * @param elementClass
     * @return
     */
    public static ParameterizedType listType(Class<?> elementClass) {
        return new ListParameterizedType(elementClass);
    }

    static class ListParameterizedType implements ParameterizedType {

        private final Class<?> elementClass;

        ListParameterizedType(Class<?> elementClass) {
            this.elementClass = elementClass;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{elementClass};
        }

        @Override
        public Type getRawType() {
            return List.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }

    public final static String getVersion(List<Method> methods) {
        List<String> strs = new ArrayList<>();

        for (Method method : methods) {
            strs.add(method.toGenericString());
        }
        Collections.sort(strs);
        return DigestUtils.md5Hex(StringUtils.join(strs, ","));
    }


    public static Method getHeartbeatMethod() {
        try {
            return HeartbeatService.class.getMethod("tick", Integer.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}
